package datas

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"

	"github.com/c-bata/go-prompt"

	"github.com/manifoldco/promptui"
)

type Data map[string]interface{}
type Datas map[string]string
type RunableFile struct {
	Name       string            `json:"name"`
	Path       string            `json:"path"`
	Options    map[string]string `json:"options"`
	Executable string            `json:"executable"`
}

func (data Data) String() string {
	pre := "---- "
	content := ""
	if f, ok := data["Code"]; ok {
		if f.(bool) {
			pre += Green(fmt.Sprintf("code: %v ", f))
		} else {
			pre += Yello(fmt.Sprintf("code: %v ", f))
		}
	}
	if f, ok := data["Op"]; ok {
		pre += Hyello(fmt.Sprintf(" Op:%s ", f))
	}
	if f, ok := data["Msg"]; ok {
		content += Blue(f)
	}
	if f, ok := data["Err"]; ok {
		content += fmt.Sprintf("\nErr: %s", Red(f))
	}
	return fmt.Sprint(pre + "\n" + content)
}

func GetHistory() (o []string) {
	h, _ := os.UserHomeDir()
	if _, err := os.Stat(filepath.Join(h, ".zsh_history")); err == nil {
		buf, _ := ioutil.ReadFile(filepath.Join(h, ".zsh_history"))
		for _, l := range bytes.Split(buf, []byte("\n")) {
			if fs := strings.SplitN(string(l), ";", 2); len(fs) == 2 {
				o = append(o, fs[1])
			}
		}
	} else {
		buf, _ := ioutil.ReadFile(filepath.Join(h, ".bash_history"))
		for _, l := range bytes.Split(buf, []byte("\n")) {
			o = append(o, string(l))
		}
	}
	return
}

var Tui = struct {
	Select         func(label string, options ...string) string
	Input          func(label string, suggest Datas) string
	InputSmartPath func(root ...string) string
}{
	Select: func(label string, options ...string) string {
		prompt := promptui.Select{
			Label:        label,
			Items:        options,
			HideSelected: true,
			Size:         10,
			Searcher: func(s string, ix int) bool {
				return strings.Contains(options[ix], s)
			},
		}
		_, result, err := prompt.Run()
		if err != nil {
			log.Println(err)
			return ""
		}
		return result
	},
	Input: func(label string, suggest Datas) string {
		return prompt.Input(label, func(d prompt.Document) (s []prompt.Suggest) {
			for k, v := range suggest {
				s = append(s, prompt.Suggest{
					Text:        k,
					Description: v,
				})
			}
			return prompt.FilterFuzzy(s, d.GetWordBeforeCursor(), true)
		})
	},
	InputSmartPath: func(root ...string) string {

		completer := func(d prompt.Document) (s []prompt.Suggest) {
			t := d.GetWordBeforeCursor()
			if root != nil {
				t = filepath.Join(root[0], t)
			}
			dir := filepath.Dir(t)
			if dir == "" {
				dir = "."
			}
			fs, err := ioutil.ReadDir(dir)
			if err != nil {
				log.Println("ioutil err:", err)
				return
			}
			for _, f := range fs {
				desc := "file"
				if f.IsDir() {
					desc = "dir"
				}
				s = append(s, prompt.Suggest{
					Text:        filepath.Join(dir, f.Name()),
					Description: desc,
				})
			}
			return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
		}
		return prompt.Input("Input a file path:", completer)
	},
}
